/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package actioncombination.problem.gridworld;


import actioncombination.logic.environment.*;
import actioncombination.common.value.Point2DIntegerValue;
import actioncombination.logic.agent.action.Action;
import actioncombination.problem.gridworld.PerceptionImpl;
import actioncombination.problem.gridworld.AgentStateImpl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;

/**
 *
 * @author gisia
 */
public class GridWorldState extends RLEnvironmentState {

    private int[][] world;
    private Point2DIntegerValue coordStart;
    private Point2DIntegerValue coordEnd;
    private ArrayList<Point2DIntegerValue> coordTargetsList;
    private ArrayList<Point2DIntegerValue> coordVisitedTargetsList;
    private ArrayList<Point2DIntegerValue> coordHolesList;

    public GridWorldState(int[][] world) {        
        this.world = world;       
        
    }
    
    public GridWorldState(int[][] world, Point2DIntegerValue start, Point2DIntegerValue end) {
        this.world = world;
        this.coordStart = start;
        this.coordEnd = end;
        this.initState();
    }

    public GridWorldState(int[][] world, Point2DIntegerValue coordStart, Point2DIntegerValue coordEnd, ArrayList<Point2DIntegerValue> coordTargets) {
        this.world = world;
        this.coordStart = coordStart;
        this.coordEnd = coordEnd;
        this.coordTargetsList = coordTargets;
    }

    public GridWorldState(int[][] world, Point2DIntegerValue coordStart, Point2DIntegerValue coordEnd, ArrayList<Point2DIntegerValue> coordTargets, ArrayList<Point2DIntegerValue> coordVisitedTargets, ArrayList<Point2DIntegerValue> coordHoles) {
        this.world = world;
        this.coordStart = coordStart;
        this.coordEnd = coordEnd;
        this.coordTargetsList = coordTargets;
        this.coordVisitedTargetsList = coordVisitedTargets;
        this.coordHolesList = coordHoles;
    }

    public int[][] getWorld() {
        return world;
    }

    public void setWorld(int[][] world) {
        this.world = world;
    }

    public void setWorld(int fil, int col, int valor) {
        this.getWorld()[fil][col] = valor;
    }

    @Override
    public Object clone() {
        int[][] nuevoMundo = new int[4][4];

        for (int fil = 0; fil < getWorld().length; fil++) {
            for (int col = 0; col < getWorld().length; col++) {
                nuevoMundo[fil][col] = getWorld()[fil][col];
            }
        }
        GridWorldState nuevoEstado = new GridWorldState(nuevoMundo);

        return nuevoEstado;
    }

    public void initState() {

        //inicializo el entorno con todo en void
        for (int fil = 0; fil < getWorld().length; fil++) {
            for (int col = 0; col < getWorld().length; col++) {
                getWorld()[fil][col] = PerceptionImpl.PERCEPTION_VOID;
            }
        }

        //Cargo las posiciones de inicio y de fin
        getWorld()[this.getCoordStart().getX()][this.getCoordStart().getY()] = PerceptionImpl.PERCEPTION_START;
        getWorld()[this.getCoordEnd().getX()][this.getCoordEnd().getY()] = PerceptionImpl.PERCEPTION_END;
        
        //Cargo el entorno con todos los targets
        Iterator iTargets=this.getCoordTargets().iterator();
        while (iTargets.hasNext()){
            Point2DIntegerValue t=(Point2DIntegerValue) iTargets.next();
            getWorld()[t.getX()][t.getY()] = PerceptionImpl.PERCEPTION_TARGET;
        }
        
        //Cargo el entorno con todos los agujeros
        Iterator iHoles=this.getCoordHoles().iterator();
        while(iHoles.hasNext()){
            Point2DIntegerValue h=(Point2DIntegerValue) iHoles.next();
            getWorld()[h.getX()][h.getY()] = PerceptionImpl.PERCEPTION_TARGET;
        }

    }

    @Override
    public String toString() {
        String str = "";

        str = str + "[ \n";
        for (int fil = 0; fil < getWorld().length; fil++) {
            str = str + "[ ";
            for (int col = 0; col < getWorld().length; col++) {
                str = str + getWorld()[fil][col] + " ";
            }
            str = str + " ]\n";
        }
        str = str + " ]";

        return str;
    }

    public int getHere(int row, int col) {
        return world[row][col];
    }

    @Override
    public boolean equals(Object obj) {
        //TODO: Falta hacer este codigo, pero por ahora no es necesario porque no uso este metodo.-
        return true;
    }  
  

    public void addTarget(Point2DIntegerValue target) {
        this.getCoordTargets().add(target);
    }

    public void removeTarget(Point2DIntegerValue target) {
        this.getCoordTargets().remove(target);
    }

    public ArrayList<Point2DIntegerValue> getCoordTargets() {
        return coordTargetsList;
    }

    public void setCoordTargets(ArrayList<Point2DIntegerValue> coordTargets) {
        this.coordTargetsList = coordTargets;
    }

    public ArrayList<Point2DIntegerValue> getCoordVisitedTargets() {
        return coordVisitedTargetsList;
    }

    public void setCoordVisitedTargets(ArrayList<Point2DIntegerValue> coordVisitedTargets) {
        this.coordVisitedTargetsList = coordVisitedTargets;
  
    }

    public Point2DIntegerValue getCoordStart() {
        return coordStart;
    }

    public void setCoordStart(Point2DIntegerValue coordStart) {
        this.coordStart = coordStart;
    }

    public Point2DIntegerValue getCoordEnd() {
        return coordEnd;
    }

    public void setCoordEnd(Point2DIntegerValue coordEnd) {
        this.coordEnd = coordEnd;
    }

    public ArrayList<Point2DIntegerValue> getCoordHoles() {
        return coordHolesList;
    }

    public void setCoordHoles(ArrayList<Point2DIntegerValue> coordHoles) {
        this.coordHolesList = coordHoles;
    }
    
     public void addHole(Point2DIntegerValue hole) {
        this.getCoordHoles().add(hole);
    }

    public void removeHole(Point2DIntegerValue hole) {
        this.getCoordHoles().remove(hole);
    }

    public void addVisitedTarget(Point2DIntegerValue target) {
        this.getCoordVisitedTargets().add(target);
    }

    public void removeVisitedTarget(Point2DIntegerValue target) {
        this.getCoordVisitedTargets().remove(target);
    }
 
}


   
